#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define BUFZISE 8192
#define DEFAULT_PORT 5320
#define CMAX 256

enum{CMD_NAME, SRC_PORT};

int execute(char *command, char *buf, int bufmax);

int main(int argc, char *argv[])
{
	struct sockaddr_in6 server;
	struct sockaddr_in6 client;
	int len;
	int port;
	int s;
	int s0;
	int cn;
	int sn;
	int rn;
	char cmd1[BUFZISE];
	char cmd2[BUFZISE];
	char recv_buf[BUFZISE];
	char send_buf[BUFZISE];
	char ipv6[CMAX];

	if(argc == 2) {
		if((port = atoi(argv[SRC_PORT])) == 0) {
			struct servent *se;
			if((se = getservbyname(argv[SRC_PORT], "tcp")) != NULL)
				port = (int)ntohs((u_short)se->s_port);
			else {
				fprintf(stderr,"getservbyname error\n");
				exit(EXIT_FAILURE);
			}
		}
	}
	else
		port = DEFAULT_PORT;
	if((s0 = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {
		perror("socket");
		exit(EXIT_FAILURE);
	}

	memset((char *)&server, 0, sizeof(server));
	server.sin6_family = AF_INET6;
	server.sin6_port = htons(port);

	if(bind(s0, (struct sockaddr *)&server, sizeof(server)) < 0) {
		perror("bind");
		exit(EXIT_FAILURE);
	}

	listen(s0, 5);

	while(1) {
		len = sizeof(client);
		if((s = accept(s0, (struct sockaddr *)&client, &len)) < 0) {
			perror("accept");
			exit(EXIT_FAILURE);
		}

		printf("connected from '%s'\n", inet_ntop(AF_INET6, &(client.sin6_addr), ipv6, CMAX));

#ifdef FORK_SERVER
	if(fork()!=0) {
		close(s);
		continue;
	}
	close(s0);
#endif
	while(1) {
		int i = 0;
		sn = sprintf(send_buf, "TCP(IPv6) >");
		send(s, send_buf, sn, 0);
	receive:
		if((rn = recv(s, &recv_buf[i], 1, 0)) < 0)
		break;

	if(recv_buf[i] != '\n') {
		i++;
		if(i<BUFZISE - 1)
			goto receive;
	}

	recv_buf[i] = '\0';
	printf("receive '%s' \n", recv_buf);

	if((cn = sscanf(recv_buf, "%s%s", cmd1, cmd2)) <= 0)
		continue;
	else if(cn == 2 && strcmp(cmd1, "show") == 0) {
		if(strcmp(cmd2, "route") == 0)
#ifdef _linux
	sn = execute("/bin/netstat -rn", send_buf, BUFZISE);
#else
	sn = execute("/usr/bin/netstat -rn", send_buf, BUFZISE);
#endif
	else if(strcmp(cmd2, "arp") == 0)
#ifdef _linux
	sn = execute("/sbin/arp -an", send_buf, BUFZISE);
#else
	sn = execute("/usr/sbin/arp -an", send_buf, BUFZISE);
#endif
	else if(strcmp(cmd2, "tcp") == 0)
#ifdef _linux
        sn = execute("/bin/netstat -tn", send_buf, BUFZISE);
#else
        sn = execute("/usr/bin/netstat -tn", send_buf, BUFZISE);
#endif
	else if(strcmp(cmd2, "nic") == 0)
		sn = execute("/sbin/ifconfig -a", send_buf, BUFZISE);
	else
		sn = sprintf(send_buf, "parameter error '%s'\n"
			     "show[route | arp | tcp | nic]\n", cmd2);
		}
	else if(cn == 1) {
			if(strcmp(cmd1, "quit") == 0)
				break;
			send_buf[0] = '\0';
			if(strcmp(cmd1, "help") != 0)
				sprintf(send_buf, "command error '%s' \n", cmd1);
				strcat(send_buf, "command:\n"
						"show route\n"
						"show arp\n"
						"show tcp\n"
						"show nic\n"
						"quit\n"
						"help\n");
			sn = strlen(send_buf);
		}
		else
			sn = sprintf(send_buf, "command error '%s'\n", cmd1);
		if(sn == 0)
			sn = sprintf(send_buf, "\n");
		if(send(s, send_buf, sn, 0) < 0)
			break;
		printf("%s", send_buf);
	}
	printf("connection closed.\n");
	close(s);
	}
	close(s0);
	return EXIT_SUCCESS;
}


int execute(char *command, char *buf, int bufmax)
{
	FILE *fp;
	int i;

	if((fp = open(command, "r")) == NULL) {
		perror(command);
		i = sprintf(buf, "server error: '%s' cannot execute.\n", command);
	}
	else {
		i = 0;
		while((buf[i] = fgetc(fp)) != EOF &&i<bufmax-1)
			i++;
		pclose(fp);
	}
	return i;
}
